package ar.com.ctrln.view.dashboard.calendar;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.zkoss.calendar.Calendars;
import org.zkoss.calendar.event.CalendarsEvent;
import org.zkoss.calendar.impl.SimpleCalendarModel;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.EventQueue;
import org.zkoss.zk.ui.event.EventQueues;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Row;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Timebox;
import org.zkoss.zul.Window;

import ar.com.ctrln.control.calendar.RegistrarEvento;
import ar.com.ctrln.persistence.model.evento.EventoCalendario;
import ar.com.ctrln.persistence.model.evento.EventoCurso;
import ar.com.ctrln.persistence.model.evento.EventoPersonal;
import ar.com.ctrln.persistence.model.evento.EventoReunion;
import ar.com.ctrln.persistence.model.evento.EventoTicket;
import ar.com.ctrln.persistence.model.evento.TemaEvento;
import ar.com.ctrln.persistence.model.evento.TipoEvento;
import ar.com.ctrln.persistence.model.sistema.cuentas.Autorizacion;
import ar.com.ctrln.view.ui.comportamientoVentana.AbstractMinimizarVentana;

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class RegistrarEventoController extends AbstractMinimizarVentana {

	private static final long serialVersionUID = -8319277137888452909L;

	@WireVariable
	private RegistrarEvento registrarEvento;

	@Wire
	private Window wRegistrar;

	@Wire
	private Combobox cboTipoEvento;

	@Wire
	private Datebox fechaInicio;

	@Wire
	private Datebox fechaFin;

	@Wire
	private Timebox horaInicio;

	@Wire
	private Timebox horaFin;

	@Wire
	private Textbox tbDescripcion;

	@Wire
	private Button bCancelarEvento;

	@Wire
	private Button btnTemaEvento;

	@Wire
	private Button bGenerarEvento;

	@Wire
	private Button btnAgregarParticipantes;

	@Wire
	private Row participantesRow;

	@Wire
	private Row temasEventoRow;

	@Wire
	private Checkbox cboxtodoElDia;

	@SuppressWarnings("rawtypes")
	private EventQueue eventoParticipantes;

	@SuppressWarnings("rawtypes")
	private EventQueue eventoTemas;

	private Date fechaDesde;

	private Date fechaHasta;

	private Date horaDesde;

	private Date horaHasta;

	private CalendarsEvent calendarsEvent;

	private Calendars wCalendario;

	private EventoCalendario evento;

	private TipoEvento tipo;

	private Set<TemaEvento> temas = new HashSet<TemaEvento>();

	@SuppressWarnings("unchecked")
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);

		eventoParticipantes = EventQueues.lookup("seleccionar_participantes",
				EventQueues.DESKTOP, true);
		eventoParticipantes.subscribe(new EventListener<Event>() {
			@Override
			public void onEvent(Event event) throws Exception {
			}
		});

		eventoTemas = EventQueues.lookup("seleccionarTemasEventos",
				EventQueues.DESKTOP, true);
		eventoTemas.subscribe(new EventListener<Event>() {
			@Override
			public void onEvent(Event event) throws Exception {
				temas = (Set<TemaEvento>) event.getData();
				tbDescripcion.setText("");
				for (TemaEvento temaEvento : temas) {
					tbDescripcion.setText(temaEvento.getNombre() + "\n");

				}
			}
		});

		cboTipoEvento.setModel(new ListModelList<TipoEvento>(registrarEvento
				.listarTiposEventos()));

		calendarsEvent = (CalendarsEvent) this.getSelf().getParent()
				.getAttribute("CalendarsEvent");

		fechaDesde = calendarsEvent.getBeginDate();
		fechaHasta = calendarsEvent.getEndDate();

		horaDesde = calendarsEvent.getBeginDate();
		horaHasta = calendarsEvent.getEndDate();

		wCalendario = (Calendars) this.getSelf().getParent()
				.getAttribute("wCalendario");

		fechaInicio.setValue(fechaDesde);
		fechaFin.setValue(fechaHasta);

		Calendar c = Calendar.getInstance();

		c.setTime(fechaDesde);

		Calendar hi = Calendar.getInstance();
		hi.set(Calendar.HOUR, c.get(Calendar.HOUR));
		hi.set(Calendar.MINUTE, c.get(Calendar.MINUTE));

		Date i = hi.getTime();

		c.setTime(fechaHasta);

		Calendar hf = Calendar.getInstance();
		hf.set(Calendar.HOUR, c.get(Calendar.HOUR));
		hf.set(Calendar.MINUTE, c.get(Calendar.MINUTE));

		Date f = hf.getTime();

		horaInicio.setValue(horaDesde);
		horaFin.setValue(horaHasta);

		cboxtodoElDia.setChecked(f.equals(i));

		if (cboxtodoElDia.isChecked()) {
			horaFin.setDisabled(true);
			horaInicio.setDisabled(true);
		}
		// fechaInicio.setConstraint(fechaConstraint);
		// fechaFin.setConstraint(fechaConstraint);
		// horaFin.setConstraint(fechaConstraint);
		// horaInicio.setConstraint(fechaConstraint);

	}

	private Constraint fechaConstraintFin = new Constraint() {

		@Override
		public void validate(Component comp, Object value)
				throws WrongValueException {

			if (((Date) value).before(fechaDesde)) {

				throw new WrongValueException(comp,
						"La Fecha de Fin debe ser mayor a la Fecha de Inicio");
			}
		}
	};

	private Constraint fechaConstraintInicio = new Constraint() {

		@Override
		public void validate(Component comp, Object value)
				throws WrongValueException {

			if (((Date) value).after(fechaHasta)) {

				throw new WrongValueException(comp,
						"La Fecha de Inicio debe ser menor a la Fecha de Fin");
			}
		}
	};

	private Constraint horaConstraintInicio = new Constraint() {

		@Override
		public void validate(Component comp, Object value)
				throws WrongValueException {

			double delta = ((fechaHasta.getTime() - fechaDesde.getTime()) / (60 * 60 * 1000));

			if (!cboxtodoElDia.isChecked()) {
				if (((Date) value).after(horaHasta) && (delta < 24.0)) {
					throw new WrongValueException(comp,
							"La Hora de Inicio debe ser menor a la Hora de Fin");
				}
			}
		}
	};

	private Constraint horaConstraintFin = new Constraint() {

		@Override
		public void validate(Component comp, Object value)
				throws WrongValueException {
			double delta = ((fechaHasta.getTime() - fechaDesde.getTime()) / (60 * 60 * 1000));
			if (!cboxtodoElDia.isChecked()) {
				if (((Date) value).before(horaDesde) && (delta < 24)) {
					throw new WrongValueException(comp,
							"La Hora de Fin debe ser mayor a la Hora de Inicio");
				}
			}
		}
	};

	@Listen("onChange =#fechaInicio")
	public void onChangeFechaInicio() {
		fechaHasta = fechaFin.getValue();
		fechaConstraintInicio.validate(fechaInicio, fechaInicio.getValue());
	}

	@Listen("onChange =#fechaFin")
	public void onChangeFechaFin() {
		fechaDesde = fechaInicio.getValue();
		fechaConstraintFin.validate(fechaFin, fechaFin.getValue());
	}

	@Listen("onChange =#horaInicio")
	public void onChangeHoraInicio() {
		fechaDesde = fechaInicio.getValue();
		fechaHasta = fechaFin.getValue();
		horaDesde = horaInicio.getValue();
		horaHasta = horaFin.getValue();
		horaConstraintInicio.validate(horaInicio, horaInicio.getValue());
		horaConstraintFin.validate(horaFin, horaFin.getValue());
	}

	@Listen("onChange =#horaFin")
	public void onChangeHoraFin() {
		fechaDesde = fechaInicio.getValue();
		fechaHasta = fechaFin.getValue();
		horaDesde = horaInicio.getValue();
		horaHasta = horaFin.getValue();
		horaConstraintInicio.validate(horaInicio, horaInicio.getValue());
		horaConstraintFin.validate(horaFin, horaFin.getValue());
	}

	@Listen("onClose = #wRegistrar")
	public void cerrarVentana() {
		if (calendarsEvent != null) {
			calendarsEvent.clearGhost();
		}
		wRegistrar.onClose();
	}

	@Listen("onClick = #bCancelarEvento")
	public void cerrar() {
		if (calendarsEvent != null) {
			calendarsEvent.clearGhost();
		}
		wRegistrar.onClose();
	}

	@Listen("onClick = #bGenerarEvento")
	public void guardarEvento() {

		Date beginDay = fechaInicio.getValue();
		Date endDay = fechaFin.getValue();
		Calendar calendarDay = Calendar.getInstance(wCalendario
				.getDefaultTimeZone());
		if (!cboxtodoElDia.isChecked()) {

			Date horaInicio = this.horaInicio.getValue();
			Date horaFin = this.horaFin.getValue();

			Calendar calendarTime = Calendar.getInstance(wCalendario
					.getDefaultTimeZone());
			calendarTime.setTime(horaInicio);

			calendarDay.setTime(beginDay);
			calendarDay.set(Calendar.HOUR_OF_DAY,
					calendarTime.get(Calendar.HOUR_OF_DAY));
			calendarDay.set(Calendar.MINUTE, calendarTime.get(Calendar.MINUTE));

			beginDay = calendarDay.getTime();

			calendarTime.setTime(horaFin);

			calendarDay.setTime(endDay);
			calendarDay.set(Calendar.HOUR_OF_DAY,
					calendarTime.get(Calendar.HOUR_OF_DAY));
			calendarDay.set(Calendar.MINUTE, calendarTime.get(Calendar.MINUTE));
			endDay = calendarDay.getTime();

		}

		evento.setContentColor(tipo.getColorRelleno());
		evento.setHeaderColor(tipo.getColorTitulo());
		evento.setTipoEvento(tipo);
		evento.setBeginDate(beginDay);
		evento.setEndDate(endDay);
		evento.setLoked(true);

		evento.setTitle(cboTipoEvento.getSelectedItem().getLabel());

		evento.setContent(tbDescripcion.getText());
		evento.setObservacion(tbDescripcion.getText());

		Autorizacion autorizacion = registrarEvento
				.buscarAutorizacion("ROLE_ADMIN");

		Collection<Autorizacion> autorizaciones = new ArrayList<Autorizacion>();
		autorizaciones.add(autorizacion);

		evento.setAutorizaciones(autorizaciones);

		registrarEvento.nuevoEvento(evento);

		if (evento.getParticipantes() != null
				&& evento.getParticipantes().size() > 0) {
			registrarEvento.nuevoParticipante(evento.getParticipantes());
		}

		// actualizacion de tema eventos
		for (TemaEvento temaEvento : temas) {
			temaEvento.setEvento(evento);
			temaEvento.setEstado(TemaEvento.AGENDADO);
			registrarEvento.actualizarTemaEvento(temaEvento);
		}

		((SimpleCalendarModel) wCalendario.getModel()).add(evento);
		wRegistrar.onClose();
	}

	@Listen("onClick = #btnAgregarParticipantes")
	public void agregarParticipantes() {
		Executions.createComponents("/zul/calendar/agregarParticipante.zul",
				wRegistrar, null);
	}

	// @Listen("onClick = #btnConsultar")
	// public void consultarParticipantes() {
	// Executions.createComponents("/zul/calendar/consultarParticipantes.zul",
	// wRegistrar, null);
	// }

	@Listen("onSelect = #cboTipoEvento")
	public void seleccionTipoEvento() {
		tipo = cboTipoEvento.getSelectedItem().getValue();
		switch (tipo.getPeso()) {
		case 1:
			evento = null;
			temasEventoRow.setVisible(true);
			participantesRow.setVisible(true);
			evento = (EventoReunion) registrarEvento
					.getEvento(RegistrarEvento.EVENTO_REUNION);
			break;
		case 2:
			evento = null;
			temasEventoRow.setVisible(false);
			participantesRow.setVisible(true);
			evento = (EventoCurso) registrarEvento
					.getEvento(RegistrarEvento.EVENTO_CURSO);
			break;
		case 3:
			evento = null;
			temasEventoRow.setVisible(false);
			participantesRow.setVisible(false);
			evento = (EventoPersonal) registrarEvento
					.getEvento(RegistrarEvento.EVENTO_PERSONAL);
			break;

		default:
			evento = null;
			evento = (EventoTicket) registrarEvento
					.getEvento(RegistrarEvento.EVENTO_PERSONAL);
			temasEventoRow.setVisible(false);
			participantesRow.setVisible(false);
			break;
		}

	}

	@Listen("onClick = #btnTemaEvento")
	public void agregarTemaEvento() {
		wRegistrar.setAttribute("temas", temas);
		Executions.createComponents("/zul/calendar/agregarTemaEvento.zul",
				wRegistrar, null);
	}

}
